package service

import (
	"bgs/cache/redisImp"
	"bgs/conf"
	"bgs/db"
	sqlc "bgs/db/sqlc"
	"bgs/grpc/client"
	"bgs/grpc/gen/proxy2/account"
	"bgs/grpc/imp/enums"
	"bgs/util"
	"context"
	"fmt"
	"go.uber.org/zap"
	"time"
)

// UserServiceImp brand bizlogic
type UserServiceImp struct {
	dao        *db.PgDao
	slog       *zap.SugaredLogger
	wechatVars *conf.WechatSection
	vars       *conf.VarsSection
	proxy      *client.GrpcClientProxy
	cacher     *cache.Adapter
}

// NewUserService initialization
func NewUserService(
	pgdao *db.PgDao,
	slog *zap.SugaredLogger,
	wechatVars *conf.WechatSection,
	vars *conf.VarsSection,
	proxy *client.GrpcClientProxy,
	adp *cache.Adapter,
) *UserServiceImp {
	return &UserServiceImp{
		dao:        pgdao,
		slog:       slog.With("module", "UserService"),
		wechatVars: wechatVars,
		vars:       vars,
		proxy:      proxy,
		cacher:     adp,
	}
}

// FetchUserAccountToken 获取用户统一token(暂时不考虑缓存)
func (s *UserServiceImp) FetchUserAccountTokenSafely(ctx context.Context, q *sqlc.Queries, userPtr *sqlc.User) (accountToken string, err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	userID := userPtr.ID
	userExt, err := s.EnsureExt(ctx, q, false, userID)
	if err != nil {
		return
	}
	slog.Infof("1、确保用户扩展信息 ok")

	accountToken = userExt.AccountToken.String

	if !userExt.AccountToken.Valid || (time.Now().Unix()-userExt.AccountTokenRefreshed.Unix()) > 6*86400 {
		if !userPtr.Mobile.Valid {
			err = fmt.Errorf("用户(%d)没有绑定手机,无法获取accountToken", userID)
			return
		}

		var grpcErr error

		mobile := userPtr.Mobile.String
		// 1判断 手机号是否已经注册
		ctxWithTimoutOfCheckMobile, cancelOfCheckMobile := s.proxy.NewContextWith(ctx)
		defer cancelOfCheckMobile()
		replyOfCheckMobile, grpcErr := s.proxy.AccountCl.CheckMobile(ctxWithTimoutOfCheckMobile, &account.CheckMobileReq{
			Mobile: mobile,
		})
		if grpcErr != nil {
			err = grpcErr
			return
		}
		slog.Infof("1、检测手机号是否注册account ok")
		if !replyOfCheckMobile.IsExist {
			slog.Infof("手机号未注册account,需要先注册")
			ctxWithTimoutOfRegister, cancelOfRegister := s.proxy.NewContextWith(ctx)
			defer cancelOfRegister()
			replyOfRegister, grpcErr := s.proxy.AccountCl.Register(ctxWithTimoutOfRegister, &account.RegisterReq{
				Mobile: mobile,
			})
			if grpcErr != nil {
				err = grpcErr
				return
			}

			slog.Infof("2、手机号注册account(%d) ok", replyOfRegister.GId)
		}

		email := ""
		app := string(enums.APPIDBGS)
		nonce := userPtr.OpenID
		secret := s.vars.AccountSecret
		raw := fmt.Sprintf("%s%s%s%s%s", mobile, email, app, nonce, secret)
		sign, signErr := util.SignSha256(raw)
		if signErr != nil {
			err = signErr
			return
		}
		reqOfCredibleLogin := &account.CredibleLoginReq{
			Mobile: mobile,
			App:    app,
			Nonce:  nonce,
			Email:  email,
			Sign:   sign,
		}

		ctxWithTimoutOfCredibleLogin, cancelOfCredibleLogin := s.proxy.NewContextWith(ctx)
		defer cancelOfCredibleLogin()

		replyOfCredibleLogin, grpcErr := s.proxy.AccountCl.CredibleLogin(ctxWithTimoutOfCredibleLogin, reqOfCredibleLogin)
		if grpcErr != nil {
			err = grpcErr
			return
		}
		accountToken = replyOfCredibleLogin.Token
		slog.Infof("2、刷新用户accountToken ok")

		// 记录刷新时间
		err = q.UpdateUserExtAccountToken(ctx, sqlc.UpdateUserExtAccountTokenParams{
			ID:           userExt.ID,
			AccountToken: sqlc.NSFromString(accountToken),
		})
		if err != nil {
			return
		}
		slog.Infof("3、记录用户accountToken刷新时间 ok")
	}

	return
}
